The platform's foundation context: tenancy and plans, identity and the federated session, the role & permission model, and the customer's organization structure. It is upstream of every other context — it publishes the token they all conform to. A supporting subdomain: bespoke multi-tenant identity that serves the core rather than differentiating.
Foundation: ASP.NET Core Identity 10 (Entity Framework Core stores, Guid keys). The identity entities below are the framework's seven AspNet* tables — ApplicationUser · UserLogin · UserClaim · UserToken · ApplicationRole · ApplicationUserRole · RoleClaim — extended with the RiverSync columns; Tenant, Organization, Application, Permission & RolePermission are extensions with no Identity equivalent. See SPEC-PRD-FED §9 (FED-17) and the ERD's DM-32 / DM-33.
Federation is the only writer of these entities. It enforces the tenant type system — riversync · customer · partner, with customer + partner allowed to coexist on one organization and riversync exclusive — the rule that exactly the riversync tenant has no organization (TEN-3), one user account per tenant, one app-role per user per application (AUTH-1), and the organization-unit / region / site structure beneath each customer. It issues the federated token that every other service trusts.
Naming: in code the tenant type is the enum TenantType = Internal · Customer · Partner — Internal is the riversync tenant; the spec vocabulary is unchanged.
Reads from: Coverage (the partner-scope resolver, for partner reads into structure) · Billing (profile bootstrap, via event). Account is the primary client (org, users, roles, structure); Admin provisions tenants; every app's BFF resolves identity here.
The words this context uses — the same in code, conversation and spec.
The consistency boundaries — one root each, guarding its invariants in a single transaction; cross-aggregate ties are by identity.
How this context meets its neighbours, with the integration pattern named on each edge.
As built (.NET 10) — the platform's most important federation fact. “Publishes the token every context conforms to” is realized as a formal two-sided contract: one writer, one thin consumer surface, consumed by every other app. The policy is expressed once in Account, projected once into Common, consumed everywhere.
| Side | What it holds | Invariant |
|---|---|---|
| WriterAccount | The sole writer and OIDC identity provider — OpenIddict on ASP.NET Core Identity 10 (EF Core, Postgres, Guid keys). Owns the persisted matrix, the claims compiler, the OpenIddict store, sign-in, and the cross-tenant writers (view-as, access grants, audit). No other app hosts an identity store or authorization server. | ARCH:VI |
| Consumer surfaceRiverSync.Common | The thin surface the five relying parties + Field compile against — Common.{Web, Claims, Domain, Federation}. Thin *Info projections (TenantInfo · PermissionInfo · RolePermissionInfo · AccessScope), the claim decoders, and the one-call relying-party wiring AddPlatformFederation(…). Layers on the OSS bases Wangkanai.Foundation.Domain + Wangkanai.Audit. | ARCH:IX |
| ConsumersPortal · Partners · Pipeline · Admin · Field | OIDC clients only. They never reference Account.Domain for federation vocabulary and never write the identity matrix — all reads are decoded from the token through Common. | ARCH:VI · IX |
| Decoder | Claim(s) | Serves |
|---|---|---|
| PermClaimCodec | perm | Permissions + scope, packed deterministically — no standalone scp claim (SPEC-PRD-FED §9) |
| EntitledAppsDecoder | apps | Entitled app keys → the product switcher (FED-5, FED-18) |
| ViewAsContext | act · vas | View-as sessions — acting user + session id (FED-13) |
Decoders are DI-free, never-throw, and carry no server FrameworkReference — so the Field WASM/PWA client decodes offline-cached tokens in the browser; Field access tokens are JWS, not JWE (SPEC-APP-FLD). The token claim contract itself — claim names and the 4 KB JWE budget — is specified in SPEC-PRD-FED §9.
The deployment mapping: this context becomes the Federation service, exposing these routes behind the gateway. Paths relative to api.riversync.com/v1; access notation per the master.
The past-tense facts this context publishes (and consumes) — its share of the platform's published language.
The modeling rules that bind this context — the master holds the full set; data integrity stays with the ERD drill-downs.
| Version | Date | Changes |
|---|---|---|
| 0.1 | 13 Jun 2026 | First draft — Tenancy, Identity and Structure merged into one Federation service (SPEC-DDD v0.6). Owns the union of their entities; routes, events and SVC-rules recomposed from the central catalog. |
| 0.2 | 14 Jun 2026 | Identity foundation set to ASP.NET Core Identity 10 (SPEC-DDD v0.8 / SPEC-ERD v0.13 / SPEC-PRD-FED v0.4) — owned identity entities are now the seven AspNet* base tables (ApplicationUser/ApplicationRole/ApplicationUserRole on IdentityUser/IdentityRole/IdentityUserRole<Guid>, plus UserLogin/UserClaim/UserToken/RoleClaim) extended with the RiverSync columns; ownership note + EmailConfirmed wording. Routes and events unchanged. |
| 0.3 | 15 Jun 2026 | Owned structure entity SiteLocation → OrganizationSite (SPEC-DDD v0.9 / SPEC-ERD v0.16). No boundary, route or event changes. |
| 0.4 | 28 Jun 2026 | Reframed as a Domain-Driven Design context (with the set, SPEC-DDD v0.14) — leads with ubiquitous language & aggregates (Tenant, ApplicationUser, ApplicationRole, OrganizationStructure) and the context relationships (upstream open-host identity that every context conforms to; the ACL bridge from Sales). The /federation API is demoted to the physical view. No ownership change. |
| 0.5 | 3 Jul 2026 | Consumption architecture (reuse) added — new §5, aligning with the as-built .NET 10 implementation (SPEC-PRD-FED v0.8): the two-sided writer / consumer contract — Account as sole writer & OIDC IdP (ARCH:VI) ↔ RiverSync.Common thin projections (TenantInfo · PermissionInfo · RolePermissionInfo · AccessScope), DI-free never-throw decoders (PermClaimCodec · EntitledAppsDecoder · ViewAsContext) and AddPlatformFederation wiring (ARCH:IX) ↔ five relying parties + Field, which never reference Account.Domain; OSS bases Wangkanai.Foundation.Domain + Wangkanai.Audit. Naming note: code enum TenantType = Internal/Customer/Partner (Internal == riversync). Later sections renumbered §6–§9. No boundary, route or event changes. |